home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc Development Framework / ODFDev / ODF / OS / FWFiles / Sources / FWFilRep.cpp < prev   
Encoding:
Text File  |  1995-11-08  |  22.8 KB  |  822 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                FWFilRep.cpp
  4. //    Release Version:    $ 1.0d11 $
  5. //
  6. //    Copyright:    1995 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "FWOS.hpp"
  11.  
  12. #ifndef FWFILREP_H
  13. #include "FWFilRep.h"
  14. #endif
  15.  
  16. #include <Limits.h>
  17.  
  18. #ifndef FWFILEAC_H
  19. #include "FWFileAc.h"
  20. #endif
  21.  
  22. #ifndef FWPRIDEB_H
  23. #include "FWPriDeb.h"
  24. #endif
  25.  
  26. #ifndef FWEXCDEF_H
  27. #include "FWExcDef.h"
  28. #endif
  29.  
  30. #if defined(FW_BUILD_MAC) && !defined(__FILES__)
  31. #include "Files.h"
  32. #endif
  33.  
  34. #if defined(FW_BUILD_WIN) && !defined(IO_H)
  35. #include "io.h"
  36. #endif
  37.  
  38. #if FW_LIB_EXPORT_PRAGMAS
  39. #pragma lib_export on
  40. #endif
  41.  
  42. #ifdef FW_BUILD_MAC
  43. #pragma segment File
  44. #endif
  45.  
  46. #ifdef FW_BUILD_WIN16
  47. extern "C" void FAR PASCAL DOS3Call();                // We use this instead of calling "Int 21h"
  48. #endif
  49.  
  50. //========================================================================================
  51. // CLASS FW_PFile
  52. //========================================================================================
  53.  
  54. //----------------------------------------------------------------------------------------
  55. // FW_PFile::FW_PFile
  56. //----------------------------------------------------------------------------------------
  57.  
  58. FW_PFile::FW_PFile(FW_CFileRep* privFileAccessRep) :
  59.     FW_CCountedPtr(privFileAccessRep)
  60. {
  61. }
  62.  
  63. //----------------------------------------------------------------------------------------
  64. // FW_PFile::FW_PFile
  65. //----------------------------------------------------------------------------------------
  66.  
  67. FW_PFile::FW_PFile(const FW_CFileSpecification& fileSpecification,
  68.                    long bufferSize,
  69.                    FW_Boolean allowCreate) :
  70.     FW_CCountedPtr(new FW_CFileRep(fileSpecification, bufferSize, allowCreate))
  71. {
  72. }
  73.  
  74. //----------------------------------------------------------------------------------------
  75. // FW_PFile::FW_PFile
  76. //----------------------------------------------------------------------------------------
  77.  
  78. FW_PFile::FW_PFile(const FW_CFileSpecification& fileSpecification,
  79.                    const FW_CAccessPermission& permission,
  80.                    long bufferSize,
  81.                    FW_Boolean allowCreate) :
  82.     FW_CCountedPtr(new FW_CFileRep(fileSpecification, permission, bufferSize, allowCreate))
  83. {
  84. }
  85.  
  86. //----------------------------------------------------------------------------------------
  87. // FW_PFile::~FW_PFile
  88. //----------------------------------------------------------------------------------------
  89.  
  90. FW_PFile::~FW_PFile()
  91. {
  92. }
  93.  
  94. //========================================================================================
  95. // CLASS FW_CFileRep
  96. //
  97. //  The FW_CFileRep class provides the implementation for FW_PFile.  It is separate 
  98. //    from FW_PFile for the purpose of reference counting.  Since this is an
  99. //    implementation class, it should not be modified by the user.
  100. //========================================================================================
  101.  
  102. //----------------------------------------------------------------------------------------
  103. //    FW_CFileRep::FW_CFileRep
  104. //----------------------------------------------------------------------------------------
  105. FW_CFileRep::FW_CFileRep(const FW_CFileSpecification& fileSpecification,
  106.                          long bufferSize,
  107.                          FW_Boolean allowCreate) :
  108.     FW_CCountedPtrRep(),
  109.     fFileSpec(fileSpecification),
  110.     fPermission(),
  111.     fFileHandle(0),
  112.     fFileBuffer(bufferSize)
  113. {
  114.     PrivOpenFile(allowCreate);
  115. }
  116.  
  117. //----------------------------------------------------------------------------------------
  118. //    FW_CFileRep::FW_CFileRep
  119. //----------------------------------------------------------------------------------------
  120.  
  121. FW_CFileRep::FW_CFileRep(const FW_CFileSpecification& fileSpecification,
  122.                          const FW_CAccessPermission& permission,
  123.                          long bufferSize,
  124.                          FW_Boolean allowCreate) :
  125.     FW_CCountedPtrRep(),
  126.     fFileSpec(fileSpecification),
  127.     fPermission(permission),
  128.     fFileHandle(0),
  129.     fFileBuffer(bufferSize)
  130. {
  131.     PrivOpenFile(allowCreate);
  132. }
  133.  
  134. //----------------------------------------------------------------------------------------
  135. //    FW_CFileRep::~FW_CFileRep
  136. //----------------------------------------------------------------------------------------
  137.  
  138. FW_CFileRep::~FW_CFileRep()
  139. {
  140.     PrivCloseFile();
  141. }
  142.  
  143. //----------------------------------------------------------------------------------------
  144. // FW_CFileRep::Read
  145. //----------------------------------------------------------------------------------------
  146. void FW_CFileRep::Read(void* destination, long count)
  147. {    
  148.     FlushAndInvalidateBuffer();
  149.     
  150.     PrivDoRead(destination, count);
  151. }
  152.  
  153. //----------------------------------------------------------------------------------------
  154. // FW_CFileRep::ReadPeek
  155. //----------------------------------------------------------------------------------------
  156. const void* FW_CFileRep::ReadPeek(long& availableReadBytes)
  157. {
  158.     long currentPosition = GetPosition();
  159.     void * source = fFileBuffer.ReadPeek(currentPosition, availableReadBytes);
  160.     
  161.     if (availableReadBytes == 0)
  162.     {
  163.         FlushAndInvalidateBuffer();
  164.         availableReadBytes = FW_Minimum(BytesToEndOfFile(), fFileBuffer.GetCapacity());
  165.         fFileBuffer.Initialize(FW_CPrivFileAccessBuffer::kReadPeek, currentPosition, availableReadBytes);
  166.         source = fFileBuffer.GetAddress();
  167.         
  168.         long savePosition = GetPosition();
  169.         PrivDoRead(source, availableReadBytes);
  170.         SetPosition(FW_CFileSystem::kFromStart, savePosition);
  171.     }
  172.     
  173.     return source;
  174. }
  175.  
  176.  
  177. //----------------------------------------------------------------------------------------
  178. // FW_CFileRep::ReadPeekAdvance
  179. //----------------------------------------------------------------------------------------
  180. void FW_CFileRep::ReadPeekAdvance(long bytesRead)
  181. {
  182.     fFileBuffer.ReadPeekAdvance(GetPosition(), bytesRead);
  183.     
  184.     SetPosition(FW_CFileSystem::kFromCurrent, bytesRead);
  185. }
  186.  
  187.  
  188. //----------------------------------------------------------------------------------------
  189. //    FW_CFileRep::Write
  190. //----------------------------------------------------------------------------------------
  191. void FW_CFileRep::Write(const void* source, long count)
  192. {
  193.     FlushAndInvalidateBuffer();
  194.     
  195.     PrivDoWrite(source, count);
  196. }
  197.  
  198.  
  199. //----------------------------------------------------------------------------------------
  200. // FW_CFileRep::WritePeek
  201. //----------------------------------------------------------------------------------------
  202. void* FW_CFileRep::WritePeek(long& availableWriteBytes)
  203. {
  204.     long currentPosition = GetPosition();
  205.     void * source = fFileBuffer.WritePeek(currentPosition, availableWriteBytes);
  206.     
  207.     if (availableWriteBytes == 0)
  208.     {
  209.         FlushAndInvalidateBuffer();
  210.         availableWriteBytes = fFileBuffer.GetCapacity();
  211.         fFileBuffer.Initialize(FW_CPrivFileAccessBuffer::kWritePeek, currentPosition, availableWriteBytes);
  212.         source = fFileBuffer.GetAddress();
  213.     }
  214.     
  215.     return source;
  216. }
  217.  
  218.  
  219. //----------------------------------------------------------------------------------------
  220. // FW_CFileRep::WritePeekAdvance
  221. //----------------------------------------------------------------------------------------
  222. void FW_CFileRep::WritePeekAdvance(long bytesWritten)
  223. {
  224.     fFileBuffer.WritePeekAdvance(GetPosition(), bytesWritten);
  225.     
  226.     long newPosition = GetPosition() + bytesWritten;
  227.     if (newPosition > GetLength())
  228.         SetLength(newPosition);
  229.     
  230.     SetPosition(FW_CFileSystem::kFromStart, newPosition);
  231. }
  232.  
  233.  
  234. //----------------------------------------------------------------------------------------
  235. //    FW_CFileRep::GetLength
  236. //----------------------------------------------------------------------------------------
  237. long FW_CFileRep::GetLength() const
  238. {
  239.     long length;
  240.  
  241. #ifdef FW_BUILD_WIN
  242.     // Since Windows does not support this feature directly, we have to reset the file
  243.     //   pointer to get the length and then restore the original position.
  244.     long oldPosition = GetPosition();
  245.     FW_FailOnError(PrivWinMoveFilePointer(0, FW_CFileSystem::kFromEnd, length));
  246.     FW_FailOnError(PrivWinMoveFilePointer(oldPosition, FW_CFileSystem::kFromStart, oldPosition));
  247. #endif
  248.  
  249. #ifdef FW_BUILD_MAC
  250.     long macEOF;
  251.  
  252.     FW_FailOnError(::GetEOF(fFileHandle, &macEOF));
  253.     length = macEOF;
  254. #endif
  255.  
  256.     return length;
  257. }
  258.  
  259.  
  260. //----------------------------------------------------------------------------------------
  261. //    FW_CFileRep::SetLength
  262. //----------------------------------------------------------------------------------------
  263. void FW_CFileRep::SetLength(long length)
  264. {
  265.     FW_CFileSystem::FileError theError = FW_CFileSystem::kNoError;
  266.  
  267.     // If file is shrinking, then assume our buffer is no longer valid.
  268.     long currentLength = GetLength();
  269.     if (length < currentLength)
  270.         FlushAndInvalidateBuffer();
  271.     
  272. #ifdef FW_BUILD_WIN16
  273.     long oldPosition = GetPosition();
  274.     FW_FailOnError(PrivWinMoveFilePointer(length, FW_CFileSystem::kFromStart, length));
  275.     
  276.     // writing 0 bytes truncates the file at the current position
  277.     char buf;
  278.     short actualWritten;
  279.     FW_CFileSystem::FileError writeError = PrivWinPrimitiveWrite(fFileHandle, 0, &buf, actualWritten);
  280.     
  281.     // move back to the old position, regardless of whether the write was successfull
  282.     if(oldPosition > length)
  283.         oldPosition = length;
  284.     FW_CFileSystem::FileError seekError = PrivWinMoveFilePointer(oldPosition, FW_CFileSystem::kFromStart, oldPosition);
  285.     
  286.     if(writeError != FW_CFileSystem::kNoError)
  287.         FW_FailOnError(writeError);
  288.     else
  289.         FW_FailOnError(seekError);
  290. #endif
  291.  
  292. #ifdef FW_BUILD_WIN32
  293.     long oldPosition = GetPosition();
  294.     SetPosition(FW_CFileSystem::kFromStart, length);
  295.     if (!::SetEndOfFile(fFileHandle))
  296.         theError = ::GetLastError();
  297.     SetPosition(FW_CFileSystem::kFromStart, oldPosition);
  298. #endif
  299.  
  300. #ifdef FW_BUILD_MAC
  301.     theError = ::SetEOF(fFileHandle, length);
  302. #endif
  303.  
  304.     FW_FailOnError(theError);
  305. }
  306.  
  307. //----------------------------------------------------------------------------------------
  308. //    FW_CFileRep::GetPosition
  309. //----------------------------------------------------------------------------------------
  310. long FW_CFileRep::GetPosition() const
  311. {
  312.     FW_CFileSystem::FileError theError = FW_CFileSystem::kNoError;
  313.     long currentPosition;
  314.  
  315. #ifdef FW_BUILD_WIN
  316.     theError = PrivWinMoveFilePointer(0, FW_CFileSystem::kFromCurrent, currentPosition);
  317. #endif
  318.  
  319. #ifdef FW_BUILD_MAC
  320.     theError = ::GetFPos(fFileHandle, ¤tPosition);
  321. #endif
  322.  
  323.     FW_FailOnError(theError);
  324.     return currentPosition;
  325. }
  326.  
  327.  
  328. //----------------------------------------------------------------------------------------
  329. //    FW_CFileRep::SetPosition
  330. //----------------------------------------------------------------------------------------
  331. void FW_CFileRep::SetPosition(FW_CFileSystem::MoveMethods positioningMode,
  332.                                        long markOffset)
  333. {
  334.     FW_CFileSystem::FileError theError = FW_CFileSystem::kNoError;
  335.     
  336. #ifdef FW_BUILD_WIN
  337.     theError = PrivWinMoveFilePointer(markOffset, positioningMode, markOffset);
  338. #endif
  339.  
  340. #ifdef FW_BUILD_MAC
  341.     long newLength = markOffset;
  342.     theError = ::SetFPos(fFileHandle, positioningMode, newLength);
  343. #endif
  344.  
  345.     switch (theError)
  346.     {
  347. #ifdef FW_BUILD_WIN16
  348.         case FW_CFileSystem::kPermissionError:
  349.             // Win16 returns this error to indicate an invalid positioningMode.
  350.             theError = FW_CFileSystem::kParameterError;
  351.             break;
  352. #endif
  353.         default:
  354.             break;
  355.     }
  356.     FW_FailOnError(theError);
  357. }
  358.  
  359.  
  360. //----------------------------------------------------------------------------------------
  361. //    FW_CFileRep::BytesToEndOfFile
  362. //----------------------------------------------------------------------------------------
  363. long FW_CFileRep::BytesToEndOfFile() const
  364. {
  365.     return (GetLength() - GetPosition());
  366. }
  367.  
  368.  
  369. //----------------------------------------------------------------------------------------
  370. //    FW_CFileRep::GetPermissions
  371. //----------------------------------------------------------------------------------------
  372. void FW_CFileRep::GetPermissions(FW_CAccessPermission& thePerms) const
  373. {
  374.     thePerms = fPermission;
  375. }
  376.  
  377.  
  378. //----------------------------------------------------------------------------------------
  379. //    FW_CFileRep::GetFileSpecification
  380. //----------------------------------------------------------------------------------------
  381. FW_CFileSpecification FW_CFileRep::GetFileSpecification() const
  382. {
  383.     return fFileSpec;
  384. }
  385.  
  386.  
  387. //----------------------------------------------------------------------------------------
  388. //    FW_CFileRep::operator==
  389. //----------------------------------------------------------------------------------------
  390. FW_Boolean FW_CFileRep::operator==(const FW_CFileRep& theOtherFile) const
  391. {
  392.     return (fFileHandle == theOtherFile.fFileHandle) && (fFileSpec == theOtherFile.fFileSpec);
  393. }
  394.  
  395.  
  396. //----------------------------------------------------------------------------------------
  397. //    FW_CFileRep::operator!=
  398. //----------------------------------------------------------------------------------------
  399. FW_Boolean FW_CFileRep::operator!=(const FW_CFileRep& theOtherFile) const
  400. {
  401.     return (fFileHandle != theOtherFile.fFileHandle) || (fFileSpec != theOtherFile.fFileSpec);
  402. }
  403.  
  404. //----------------------------------------------------------------------------------------
  405. //    FW_CFileRep::PrivOpenFile
  406. //
  407. //    Opens the file using the permissions set with SetPermission.  If no permissions were
  408. //    set, it tries to open the file for exclusive access.  If the file is already open,
  409. //    nothing happens.  If any other errors occur, they are thrown as exceptions.
  410. //----------------------------------------------------------------------------------------
  411. void FW_CFileRep::PrivOpenFile(FW_Boolean allowCreate)
  412. {
  413.     FW_CFileSystem::FileError theError = FW_CFileSystem::kNoError;
  414.     FW_CAccessPermission::Access accessMode;
  415.     FW_CAccessPermission::Deny denyMode;
  416.  
  417.     fPermission.GetPermission(accessMode, denyMode);
  418.  
  419. #ifdef FW_BUILD_WIN
  420.     FW_CDynamicString fileName;
  421.  
  422.     fFileSpec.GetFullPath(fileName);
  423. #endif
  424.  
  425. #ifdef FW_BUILD_WIN16
  426.     OFSTRUCT Buffer;
  427.     fFileHandle = ::OpenFile((const FW_Char*)fileName, &Buffer, accessMode | denyMode);
  428.     if (fFileHandle == FW_kInvalidAccessHandle)
  429.         theError = Buffer.nErrCode;
  430. #endif
  431.  
  432. #ifdef FW_BUILD_WIN32
  433.     // If we allowCreate, always open the file.  Otherwise, open only if it 
  434.     // already exists.
  435.     long openMode = (allowCreate ? OPEN_ALWAYS : OPEN_EXISTING);
  436.     
  437.     fFileHandle = ::CreateFile((const FW_Char*)fileName, 
  438.                                accessMode, 
  439.                                denyMode, 
  440.                                NULL,
  441.                                openMode, 
  442.                                FILE_ATTRIBUTE_NORMAL, 
  443.                                (HANDLE)NULL);
  444.                                
  445.     if (fFileHandle == FW_kInvalidAccessHandle)
  446.         theError = ::GetLastError();
  447. #endif
  448.  
  449. #ifdef FW_BUILD_MAC
  450.     // If we allowCreate, then try creating the file.  If the file already 
  451.     // exists, we will FW_CATCH the attempt to re-create it and merrily roll 
  452.     // along.  If the file does not exist, it will when we're done.
  453.     if (allowCreate)
  454.     {
  455.         FW_TRY
  456.         {
  457.             FW_CFileSystem::CreateFile(fFileSpec, FALSE);
  458.         }
  459.         FW_CATCH_BEGIN
  460.         FW_CATCH(FW_XException, theException)
  461.         {
  462.             if (theException.GetPlatformError() != FW_CFileSystem::kFileExists)
  463.                 FW_THROW_SAME();
  464.         }
  465.         FW_CATCH_END
  466.  
  467.         // At this point, the file exists (modulo another thread nuking it).
  468.     }
  469.  
  470.     // Check to see if file sharing exists on this volume.  If it does, open the file using
  471.     // deny modes.
  472.     FSSpec theMacSpec;
  473.  
  474.     fFileSpec.MacGetFSSpec(theMacSpec);
  475.  
  476.     if (FW_CFileSystem::MacIsVolumeShared(theMacSpec.vRefNum))
  477.     {
  478.         HParamBlockRec paramBlock;
  479.  
  480.         paramBlock.fileParam.ioNamePtr = (StringPtr) & (theMacSpec.name);
  481.         paramBlock.fileParam.ioVRefNum = theMacSpec.vRefNum;
  482.         paramBlock.fileParam.ioDirID = theMacSpec.parID;
  483.         paramBlock.accessParam.ioDenyModes = accessMode | denyMode;
  484.  
  485.         theError = ::PBHOpenDenySync(¶mBlock);
  486.         fFileHandle = paramBlock.fileParam.ioFRefNum;
  487.     }
  488.     else
  489.         theError = ::FSpOpenDF(&(theMacSpec), accessMode, &fFileHandle);
  490.     
  491. #endif    
  492.     
  493.     FW_FailOnError(theError);
  494. }
  495.  
  496. //----------------------------------------------------------------------------------------
  497. //    FW_CFileRep::PrivCloseFile
  498. //----------------------------------------------------------------------------------------
  499. void FW_CFileRep::PrivCloseFile()
  500. {
  501.     FW_CFileSystem::FileError theError = FW_CFileSystem::kNoError;
  502.  
  503.     FlushAndInvalidateBuffer();
  504.  
  505. #if 0
  506. //#ifdef FW_BUILD_WIN16
  507.     FW_FileAccessHandle handle = fFileHandle;
  508.     
  509.     __asm {
  510.         mov        bx, [handle]
  511.         mov        ah, 03Eh
  512.     }
  513.     
  514.     DOS3Call();
  515.         
  516.     __asm {
  517.         jc        _error
  518.         xor        ax, ax
  519.     }
  520.  
  521.     _error:
  522.         
  523.     __asm {
  524.         mov        theError, ax
  525.     }
  526. #endif
  527.  
  528. #ifdef FW_BUILD_WIN32
  529.     if(!::CloseHandle(fFileHandle))
  530.         theError = ::GetLastError();
  531. #endif
  532.  
  533. #ifdef FW_BUILD_MAC
  534.     theError = ::FSClose(fFileHandle);
  535. #endif
  536.  
  537.     FW_FailOnError(theError);
  538.         
  539.     fFileHandle = FW_kInvalidAccessHandle;
  540. }
  541.  
  542.  
  543. #ifdef FW_BUILD_WIN16
  544. //----------------------------------------------------------------------------------------
  545. //    FW_CFileRep::PrivWinGetIOBufferSize
  546. //----------------------------------------------------------------------------------------
  547. short FW_CFileRep::PrivWinGetIOBufferSize(long bytesDesired,
  548.                                                      const void* buffer)
  549. {
  550.     short offset = (short)(long)buffer;
  551.     long max = 0x10000L - offset;
  552.     if(max > bytesDesired)
  553.         max = bytesDesired;
  554.     return max > 16384 ? 16384 : (short)max;
  555. }
  556.                                        
  557.  
  558. //----------------------------------------------------------------------------------------
  559. //    FW_CFileRep::PrivWinPrimitiveRead
  560. //----------------------------------------------------------------------------------------
  561. FW_CFileSystem::FileError FW_CFileRep::PrivWinPrimitiveRead(FW_FileAccessHandle handle,
  562.                                                                      short bytesToRead,
  563.                                                                      void* buffer,
  564.                                                                      short& bytesActuallyRead)
  565. {
  566.     FW_CFileSystem::FileError theError;
  567.     
  568.     __asm {
  569.         mov        ah, 03Fh
  570.         mov        bx, [handle]
  571.         mov        cx, [bytesToRead]
  572.         push    ds
  573.         lds        dx, [buffer]
  574.     }
  575.     
  576.     DOS3Call();
  577.         
  578.     __asm {
  579.         pop        ds
  580.         jc        _error
  581.         les        bx, [bytesActuallyRead]
  582.         mov        es:[bx], ax
  583.         xor        ax, ax
  584.     }
  585.     
  586.     _error:
  587.     
  588.     __asm {
  589.         mov        theError, ax
  590.     };
  591.     
  592.     return (theError);
  593. }
  594.  
  595.  
  596. //----------------------------------------------------------------------------------------
  597. //    FW_CFileRep::PrivWinPrimitiveWrite
  598. //----------------------------------------------------------------------------------------
  599. FW_CFileSystem::FileError FW_CFileRep::PrivWinPrimitiveWrite(FW_FileAccessHandle handle,
  600.                                                                       short bytesToWrite,
  601.                                                                       const void* buffer,
  602.                                                                       short& bytesActuallyWritten)
  603. {
  604.     FW_CFileSystem::FileError theError;
  605.     
  606.     __asm {
  607.         mov        ah, 040h
  608.         mov        bx, [handle]
  609.         mov        cx, [bytesToWrite]
  610.         push    ds
  611.         lds        dx, [buffer]
  612.     }
  613.     
  614.     DOS3Call();
  615.         
  616.     __asm {
  617.         pop        ds
  618.         jc        _error
  619.         les        bx, [bytesActuallyWritten]
  620.         mov        es:[bx], ax
  621.         xor        ax, ax
  622.     }
  623.     
  624.     _error:
  625.     
  626.     _asm {
  627.         mov        theError, ax
  628.     };
  629.     
  630.     return (theError);
  631. }
  632. #endif
  633.  
  634. //----------------------------------------------------------------------------------------
  635. // FW_CFileRep::PrivDoRead
  636. //----------------------------------------------------------------------------------------
  637. void FW_CFileRep::PrivDoRead(void* destination, long count)
  638. {
  639.     FW_CFileSystem::FileError theError = FW_CFileSystem::kNoError;
  640.     
  641.     FW_ASSERT (count >= 0);
  642.         
  643. #ifdef FW_BUILD_WIN16
  644.     long toRead = count;
  645.     while(toRead > 0)
  646.     {
  647.         short readNow = PrivWinGetIOBufferSize(toRead, destination);
  648.         short actualRead;
  649.         theError = PrivWinPrimitiveRead(fFileHandle, readNow, destination, actualRead);
  650.         
  651.         if(theError != 0)
  652.             break;
  653.             
  654.         toRead -= actualRead;
  655.  
  656.         if(actualRead < readNow)
  657.             break;
  658.             
  659.         destination = ((char __huge*) destination) + toRead;
  660.     }
  661.     
  662.     if (toRead != 0)
  663.         theError = FW_CFileSystem::kEndOfFileReached;
  664. #endif
  665.  
  666. #ifdef FW_BUILD_WIN32
  667.     DWORD actualRead;
  668.     if(!::ReadFile(fFileHandle, destination, count, &actualRead, NULL))
  669.         theError = ::GetLastError();
  670. #endif
  671.  
  672. #ifdef FW_BUILD_MAC
  673.     theError = ::FSRead(fFileHandle, &count, destination);
  674. #endif
  675.  
  676.     FW_FailOnError(theError);
  677. }
  678.  
  679.  
  680. //----------------------------------------------------------------------------------------
  681. //    FW_CFileRep::PrivDoWrite
  682. //----------------------------------------------------------------------------------------
  683. void FW_CFileRep::PrivDoWrite(const void* source, long count)
  684. {
  685.     FW_CFileSystem::FileError theError = FW_CFileSystem::kNoError;
  686.  
  687.     FW_ASSERT (count > 0);
  688.     
  689. #ifdef FW_BUILD_WIN16
  690.     long toWrite = count;
  691.     while(toWrite > 0)
  692.     {
  693.         short writeNow = PrivWinGetIOBufferSize(toWrite, source);
  694.         short actualWritten;
  695.         theError = PrivWinPrimitiveWrite(fFileHandle, writeNow, source, actualWritten);
  696.         
  697.         if(theError != 0)
  698.             break;
  699.             
  700.         toWrite -= actualWritten;
  701.  
  702.         if(actualWritten < writeNow)
  703.             break;
  704.             
  705.         source = ((const char __huge*) source) + toWrite;
  706.     }
  707.         
  708.     if (toWrite != 0)
  709.         theError = FW_CFileSystem::kDiskFull;
  710. #endif
  711.  
  712. #ifdef FW_BUILD_WIN32
  713.     DWORD actualWrite;
  714.     if(!::WriteFile(fFileHandle, source, count, &actualWrite, NULL))
  715.         theError = ::GetLastError();
  716. #endif
  717.  
  718. #ifdef FW_BUILD_MAC
  719.      theError = ::FSWrite(fFileHandle, &count, source);
  720. #endif
  721.  
  722.     FW_FailOnError(theError);
  723. }
  724.  
  725.  
  726. //----------------------------------------------------------------------------------------
  727. //    FW_CFileRep::GetFileHandle
  728. //----------------------------------------------------------------------------------------
  729. FW_FileAccessHandle FW_CFileRep::GetFileHandle() const
  730. {
  731.     return fFileHandle;
  732. }
  733.  
  734.  
  735. #ifdef FW_BUILD_WIN
  736. //----------------------------------------------------------------------------------------
  737. //    FW_CFileRep::PrivWinMoveFilePointer
  738. //----------------------------------------------------------------------------------------
  739. FW_CFileSystem::FileError FW_CFileRep::PrivWinMoveFilePointer(long markOffset,
  740.                                                                          FW_CFileSystem::MoveMethods positioningMode,
  741.                                                                          long& newPosition) const
  742. {
  743.     FW_CFileSystem::FileError theError = FW_CFileSystem::kNoError;
  744.  
  745. #ifdef FW_BUILD_WIN16
  746.     FW_FileAccessHandle handle = fFileHandle;
  747.     
  748.     __asm {
  749.         mov     ax, [positioningMode]
  750.         mov     ah, 42h
  751.         mov        bx, [handle]
  752.         mov     dx, word ptr [markOffset]
  753.         mov     cx, word ptr [markOffset+2]
  754.     }
  755.     
  756.     DOS3Call();
  757.         
  758.     __asm {
  759.         jc        _error
  760.         les     bx, [newPosition]
  761.         mov     word ptr es:[bx], ax
  762.         mov     word ptr es:[bx+2], dx
  763.         xor     ax, ax
  764.     }
  765.             
  766.     _error:
  767.     
  768.     __asm {
  769.         mov        theError, ax
  770.     }
  771. #endif
  772.  
  773. #ifdef FW_BUILD_WIN32
  774.     newPosition = ::SetFilePointer(fFileHandle, markOffset, NULL, positioningMode);
  775.     if (newPosition == FW_kInvalidSeek)
  776.         theError = ::GetLastError();
  777. #endif
  778.  
  779.     return theError;
  780. }
  781. #endif
  782.  
  783.  
  784. //----------------------------------------------------------------------------------------
  785. // FW_CFileRep::FlushAndInvalidateBuffer
  786. //
  787. // If the buffer is "dirty", it needs to be written to disk. First, we'll get
  788. // all the information of the fileBuffer object, invalidate the object, and
  789. // then write the data to the disk. We must invalidate the fileBuffer object
  790. // before calling Write() as it calls FlushAndInvalidateBuffer().
  791. //----------------------------------------------------------------------------------------
  792. void FW_CFileRep::FlushAndInvalidateBuffer()
  793. {
  794.     long currentPosition;
  795.     long bufferInitialPosition;
  796.     void * bufferAddress;
  797.     long bytesWritten;
  798.     FW_Boolean dirtyBuffer = fFileBuffer.IsDirty();
  799.     
  800.     // If the buffer is dirty, get buffer info prior to invalidating buffer
  801.     if (dirtyBuffer)
  802.     {
  803.         currentPosition = GetPosition();
  804.         bufferInitialPosition = fFileBuffer.GetInitialPosition();
  805.         bufferAddress = fFileBuffer.GetAddress();
  806.         bytesWritten = fFileBuffer.GetBytesWritten();
  807.     }
  808.     
  809.     // Then invalidate the buffer (whether it's dirty or not)
  810.     fFileBuffer.Invalidate();
  811.     
  812.     // Now write the dirty buffer. Note that Write() calls FlushAndInvalidateBuffer().
  813.     if (dirtyBuffer)
  814.     {
  815.         SetPosition(FW_CFileSystem::kFromStart, bufferInitialPosition);
  816.         PrivDoWrite(bufferAddress, bytesWritten);
  817.         SetPosition(FW_CFileSystem::kFromStart, currentPosition);
  818.     }
  819. }
  820.  
  821.  
  822.